﻿using NetTaste;
using Newtonsoft.Json;
using SimpleInOutControl.Common;
using SimpleInOutControl.DBModels;
using SimpleInOutControl.Utility;
using System.ComponentModel;
using System.Runtime.InteropServices;
using static SimpleInOutControl.Utility.CHCNetSDK.NET_DVR_DECCHANSTATUS.objectInfo;

namespace SimpleInOutControl.Services
{
    public class PersonInfoService: BaseService
    {
        public bool AddData(PersonInfo dto, Dictionary<int, DeviceInfo> devices)
        {
            
            using (var client = DataBaseHelper.GetSqlSugarClient())
            {
                var count = client.Insertable(dto).ExecuteCommand();

                #region 向设备添加人员信息
                foreach (var deviceKey in devices.Keys)
                {
                    if (devices[deviceKey].DeviceType == 1)
                    {
                        var m_lSetUserCfgHandle = -1;
                        if (m_lSetUserCfgHandle != -1)
                        {
                            if (CHCNetSDK.NET_DVR_StopRemoteConfig(m_lSetUserCfgHandle))
                            {
                                m_lSetUserCfgHandle = -1;
                            }
                        }
                        string sURL = "PUT /ISAPI/AccessControl/UserInfo/SetUp?format=json";
                        IntPtr ptrURL = Marshal.StringToHGlobalAnsi(sURL);
                        m_lSetUserCfgHandle = CHCNetSDK.NET_DVR_StartRemoteConfig(deviceKey, CHCNetSDK.NET_DVR_JSON_CONFIG, ptrURL, sURL.Length, null, IntPtr.Zero);
                        if (m_lSetUserCfgHandle < 0)
                        {
                            //MessageBox.Show("NET_DVR_StartRemoteConfig fail [url:PUT /ISAPI/AccessControl/UserInfo/SetUp?format=json] error:" + CHCNetSDK.NET_DVR_GetLastError());
                            Console.WriteLine("NET_DVR_StartRemoteConfig fail [url:PUT /ISAPI/AccessControl/UserInfo/SetUp?format=json] error:" + CHCNetSDK.NET_DVR_GetLastError());
                            Marshal.FreeHGlobal(ptrURL);
                            //return;
                        }
                        else
                        {
                            SendUserInfo(dto, m_lSetUserCfgHandle);
                            Marshal.FreeHGlobal(ptrURL);
                        }
                    }
                }
                
                #endregion

                return count > 0;
            }
        }
        public bool UpdateData(PersonInfo dto)
        {
            using (var client = DataBaseHelper.GetSqlSugarClient())
            {
                var count = client.Updateable(dto).IgnoreColumns(ignoreAllNullColumns: true, ignoreAllDefaultValue: true).ExecuteCommand();
                return count > 0;
            }
        }

        public bool DeleteData(int id) {
            using (var client = DataBaseHelper.GetSqlSugarClient())
            {
                var obj = client.Queryable<PersonInfo>().Where(u => u.ID == id).First();
                if (obj == null)
                {
                    return false;
                }
                var count = client.Deleteable(obj).ExecuteCommand();
                return count > 0;
            }
        }

        public PersonInfo GetData(int id)
        {
            using (var client = DataBaseHelper.GetSqlSugarClient())
            {
                var data = client.Queryable<PersonInfo>().Where(u=>u.ID==id).First();
                return data;
            }
        }

        public List<PersonInfo> GetPageData(PagingRequest<UserInfo> dto)
        {
            using (var client = DataBaseHelper.GetSqlSugarClient())
            {
                var datas = client.Queryable<PersonInfo>().ToList();
                return datas;
            }
        }

        private void SendUserInfo(PersonInfo personInfo,int m_lSetUserCfgHandle)
        {
            CUserInfoCfg JsonUserInfo = new CUserInfoCfg();
            JsonUserInfo.UserInfo = new CUserInfo();
            JsonUserInfo.UserInfo.employeeNo = personInfo.Number;
            JsonUserInfo.UserInfo.name = personInfo.Name;
            JsonUserInfo.UserInfo.userType = "normal";
            JsonUserInfo.UserInfo.Valid = new CValid();
            JsonUserInfo.UserInfo.Valid.enable = true;
            JsonUserInfo.UserInfo.Valid.beginTime = "2017-08-01T17:30:08";
            JsonUserInfo.UserInfo.Valid.endTime = "2037-12-12T23:59:59";
            JsonUserInfo.UserInfo.Valid.timeType = "local";

            JsonUserInfo.UserInfo.doorRight = "1";
            JsonUserInfo.UserInfo.RightPlan = new List<CRightPlan>();
            CRightPlan JsonRightPlan = new CRightPlan();
            JsonRightPlan.doorNo = 1;
            JsonRightPlan.planTemplateNo = "1";
            JsonUserInfo.UserInfo.RightPlan.Add(JsonRightPlan);
            //     JsonUserInfo.UserInfo.userVerifyMode = "face";
            string strJsonUserInfo = JsonConvert.SerializeObject(JsonUserInfo, Formatting.Indented,
            new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });

            //    public Int32 m_lGetUserCfgHandle = -1;
            //Int32 m_lSetUserCfgHandle = -1;
            //public Int32 m_lDelUserCfgHandle = -1;

            byte[] byJsonUserInfo = System.Text.Encoding.UTF8.GetBytes(strJsonUserInfo);
            //byte[] byJsonUserInfo = System.Text.Encoding.UTF8.GetBytes(personInfo.ToJson(true));
            IntPtr ptrJsonUserInfo = Marshal.AllocHGlobal(byJsonUserInfo.Length);
            Marshal.Copy(byJsonUserInfo, 0, ptrJsonUserInfo, byJsonUserInfo.Length);

            IntPtr ptrJsonData = Marshal.AllocHGlobal(1024);
            for (int i = 0; i < 1024; i++)
            {
                Marshal.WriteByte(ptrJsonData, i, 0);
            }

            int dwState = (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_SUCCESS;
            uint dwReturned = 0;
            while (true)
            {
                dwState = CHCNetSDK.NET_DVR_SendWithRecvRemoteConfig(m_lSetUserCfgHandle, ptrJsonUserInfo, (uint)byJsonUserInfo.Length, ptrJsonData, 1024, ref dwReturned);
                string strJsonData = Marshal.PtrToStringAnsi(ptrJsonData);
                if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_NEEDWAIT)
                {
                    Thread.Sleep(10);
                    continue;
                }
                else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_FAILED)
                {
                    //MessageBox.Show("Set User Fail error:" + CHCNetSDK.NET_DVR_GetLastError());
                    Console.WriteLine("Set User Fail error:" + CHCNetSDK.NET_DVR_GetLastError());
                    break;
                }
                else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_SUCCESS)
                {
                    //返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了，但并不代表下发成功，比如有些设备可能因为人员已存在等原因下发失败，所以需要解析Json报文
                    CResponseStatus JsonResponseStatus = new CResponseStatus();
                    JsonResponseStatus = JsonConvert.DeserializeObject<CResponseStatus>(strJsonData);

                    if (JsonResponseStatus.statusCode == 1)
                    {
                        //MessageBox.Show("Set User Success");
                        Console.WriteLine("Set User Success");
                    }
                    else
                    {
                        //MessageBox.Show("Set User Fail, ResponseStatus.statusCode" + JsonResponseStatus.statusCode);
                        Console.WriteLine("Set User Fail, ResponseStatus.statusCode" + JsonResponseStatus.statusCode);
                    }
                    break;
                }
                else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_FINISH)
                {
                    //下发人员时：dwState其实不会走到这里，因为设备不知道我们会下发多少个人，所以长连接需要我们主动关闭
                    //MessageBox.Show("Set User Finish");
                    Console.WriteLine("Set User Finish");
                    break;
                }
                else if (dwState == (int)CHCNetSDK.NET_SDK_SENDWITHRECV_STATUS.NET_SDK_CONFIG_STATUS_EXCEPTION)
                {
                    //MessageBox.Show("Set User Exception error:" + CHCNetSDK.NET_DVR_GetLastError());
                    
                    Console.WriteLine("Set User Exception error:" + CHCNetSDK.NET_DVR_GetLastError());
                    break;
                }
                else
                {
                    //MessageBox.Show("unknown Status error:" + CHCNetSDK.NET_DVR_GetLastError());
                    Console.WriteLine("unknown Status error:" + CHCNetSDK.NET_DVR_GetLastError());
                    break;
                }
            }
            if (m_lSetUserCfgHandle != -1)
            {
                if (CHCNetSDK.NET_DVR_StopRemoteConfig(m_lSetUserCfgHandle))
                {
                    m_lSetUserCfgHandle = -1;
                }
            }
            Marshal.FreeHGlobal(ptrJsonUserInfo);
            Marshal.FreeHGlobal(ptrJsonData);
        }

    }

    public class CResponseStatus
    {
        public string requestURL { get; set; }
        public int statusCode { get; set; }
        public string statusString { get; set; }
        public string subStatusCode { get; set; }
        public int errorCode { get; set; }
        public string errorMsg { get; set; }
    }

    public class CUserInfoCfg
    {
        public CUserInfo UserInfo { get; set; }
    }

    public class CRightPlan
    {
        [DefaultValue(-1)]
        public int doorNo { get; set; }
        [DefaultValue(null)]
        public string planTemplateNo { get; set; }
    }

    public class CUserInfo
    {
        public string employeeNo { get; set; }
        public string name { get; set; }
        public string userType { get; set; }
        public bool closeDelayEnabled { get; set; }
        public CValid Valid { get; set; }
        public string belongGroup { get; set; }
        public string password { get; set; }
        public string doorRight { get; set; }
        public List<CRightPlan> RightPlan { get; set; }
        public int maxOpenDoorTime { get; set; }
        public int openDoorTime { get; set; }
        public int roomNumber { get; set; }
        public int floorNumber { get; set; }
        public bool doubleLockRight { get; set; }
        public bool alwaysOpenRight { get; set; }
        public bool localUIRight { get; set; }
        public string userVerifyMode { get; set; }
    }

    public class CValid
    {
        public bool enable { get; set; } //req
        public string beginTime { get; set; } //req
        public string endTime { get; set; } //req
        [DefaultValue(null)]
        public string timeType { get; set; }
    }
}
